﻿using RPCServer.Core;
using RPCServer.Struct;
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace RPCServer.Network
{
    //class RecvArgs
    //{
    //    readonly static Pool<RecvArgs> _pool = new(() => { return new RecvArgs(); });

    //    public UserToken userToken;

    //    public MBuffer data;

    //    public static RecvArgs GetArgs()
    //    {
    //        return _pool.Take();
    //    }

    //    public static RecvArgs GetArgs(UserToken userToken, DataBuffer msg)
    //    {
    //        RecvArgs args = _pool.Take();
    //        args.data = msg;
    //        args.userToken = userToken;
    //        return args;
    //    }

    //    public static void RecycleArgs(RecvArgs args)
    //    {
    //        args.Clear();
    //        _pool.Recycle(args);
    //    }

    //    public void Clear()
    //    {
    //        userToken = default;
    //        data = default;
    //    }

    //    //public RecvArgs(UserToken userToken, object msg)
    //    //{
    //    //    this.userToken = userToken;
    //    //    this.msg = msg;
    //    //}
    //}

    class TCPServer
    {
        Socket _listener;

        NetworkSetting _setting;

        int _curConnectNum;

        Semaphore _maxClients;

        SyncPool<NetEventArgs> _freeArgs;

        ConcurrentQueue<NetEventArgs> _useArgs;

        readonly ConcurrentQueue<RecvArgs> _recvMsg = new();
        internal ConcurrentQueue<RecvArgs> RecvMsg => _recvMsg;

        #region TCPServer()
        public TCPServer(NetworkSetting setting)
        {
            _setting = setting;
        }
        #endregion

        public void Start()
        {
            if (_listener != null) { return; }

            _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _listener.Bind(_setting.Address);
            _listener.Listen(_setting.ListenCount);

            _maxClients = new Semaphore(_setting.MaxConnectCount, _setting.MaxConnectCount);
            _freeArgs = new SyncPool<NetEventArgs>(CreateArgs);
            _useArgs = new();
            _recvMsg.Clear();
            _curConnectNum = 0;

            Console.WriteLine("Net Start:: {0}:{1}", _setting.Address.Address.ToString(), _setting.Address.Port);

            StartAccpt(null);
        }

        void StartAccpt(SocketAsyncEventArgs e)
        {
            if (e == null)
            {
                e = new SocketAsyncEventArgs();
                e.Completed += Completed;
            }
            else
            {
                e.AcceptSocket = null;
            }

            _maxClients.WaitOne();

            if (!_listener.AcceptAsync(e)) //如果立即有链接
            {
                ProcessAccept(e);
            }
        }

        //!!!事件绑定时，回收对象记得解绑!!!
        void ProcessAccept(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                Interlocked.Increment(ref _curConnectNum);

                Socket socket = e.AcceptSocket;
                Console.WriteLine("[{1}] 进入链接\n当前连接数:{0}", _curConnectNum, socket.RemoteEndPoint.ToString());

                RecvArgs recvArgs = MObjectManager.Instance.GetItem<RecvArgs>();
                MBuffer buffer = GlobalMBufferManager.Instance.GetBuffer(_setting.BufferSize);

                recvArgs.SetBuffer(buffer);

                UserToken token = MObjectManager.Instance.GetItem<UserToken>();
                token.LastTicks = DateTime.UtcNow.Ticks;
                token.Socket = socket;
                token.IsClose = false;

                recvArgs.Completed -= Completed;
                recvArgs.Completed += Completed;

                SendArgs sendArgs = MObjectManager.Instance.GetItem<SendArgs>();
                sendArgs.Completed -= Completed;
                sendArgs.Completed += Completed;

                recvArgs.UserToken = token;
                sendArgs.UserToken = token;

                StartReceive(recvArgs);
                StartAccpt(e);
            }
            else
            {
                Close();
            }
        }

        void Completed(object sender, SocketAsyncEventArgs e)
        {
            switch (e.LastOperation)
            {
                case SocketAsyncOperation.Receive:
                    ProcessRecv(e as RecvArgs);
                    break;
                case SocketAsyncOperation.Send:
                    ProcessSend(e as SendArgs);
                    break;
                case SocketAsyncOperation.Accept:
                    ProcessAccept(e);
                    break;
                default:
                    Console.WriteLine("IOCompleted false");
                    break;
            }
        }

        void StartReceive(RecvArgs e)
        {
            UserToken token = e.UserToken as UserToken;

            if (!token.Socket.ReceiveAsync(e)) //立即有数据
            {
                ProcessRecv(e);
            }
        }

        void ProcessRecv(RecvArgs e)
        {
            UserToken token = e.UserToken as UserToken;

            if (e.SocketError != SocketError.Success || e.BytesTransferred < 1)
            {
                token.IsClose = true;
                token.LastTicks = long.MinValue;
                return;
            }
            //TODO  处理流数据
            token.LastTicks = DateTime.UtcNow.Ticks;
            e.SetRecvCount(e.BytesTransferred);
            StartReceive(e);
        }

        public void StartSend(SendArgs e)
        {
            if (e.HasSendData)
            {
                UserToken token = e.UserToken as UserToken;
                token.Socket.SendAsync(e);
            }
        }

        void ProcessSend(SendArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                StartSend(e);
            }
            else
            {
                LogManager.Instance.LogError($"发送失败，剩余数据 {e.SendBuffer.Count} 未发送！");
            }
        }

        void HeartBreath()
        {
            Console.WriteLine("HeartBreath");



            //TimeManager.Instance.TimeTaskScheduler.AddTask(HeartBreath, 1000);
        }

        NetEventArgs CreateArgs()
        {
            NetEventArgs e = new();
            e.RecvArgs = new();
            e.SendArgs = new();
            e.Token = new();
            e.RecvArgs.UserToken = e.Token;
            e.SendArgs.UserToken = e.Token;
            e.Token.Parser = new MBufferPacket();
            e.Token.Parser.Complete += (msg) =>
            {
                _recvMsg.Enqueue(RecvArgs.GetArgs(e.Token, msg));
                Console.WriteLine($"TCPServer Receive from [{e.Token.IP}] Len:{msg.Count}");
            };
            return e;
        }

        void BeforeRecycleArgs(NetEventArgs args)
        {
            args.Token.Clear();
            _bufferManager.RecycleBuffer(args);

            Interlocked.Decrement(ref _curConnectNum);
            Console.WriteLine("[断开链接] 当前链接数：{0}", _curConnectNum);
            _maxClients.Release();
        }

        void BeforeTakeArgs(NetEventArgs args)
        {
            _bufferManager.SetBuffer(args);
        }

        public void Close()
        {
            _listener.Close();
        }
    }
}
